package com.ruoyi.buy.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.buy.domain.entity.PO.*;
import com.ruoyi.buy.mapper.PO.*;
import com.ruoyi.buy.service.ICommonService;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 参数配置 服务层实现
 * 
 * @author ruoyi
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CommonServiceImpl implements ICommonService
{

    @Resource
    private SysNumberMapper sysNumberMapper;

    @Resource
    private BuySpaPriceMapper buySpaPriceMapper;

    @Resource
    private BuySpaMainInfoMapper buySpaMainInfoMapper;

    @Resource
    private BuyPurchaseBillItemMapper buyPurchaseBillItemMapper;

    @Resource
    private BuyMaterialBillItemMapper buyMaterialBillItemMapper;

    @Resource
    private InvInoutBillMapper invInoutBillMapper;

    @Resource
    private InvInoutBillItemMapper invInoutBillItemMapper;

    @Resource
    private InvInventoryInfoMapper invInventoryInfoMapper;

    @Override
    public String getNo(String type) {
//        //先查有没有这个编号
        SysNumber sysNumber = new SysNumber();
        sysNumber.setType(type);

        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String date = format.format(new Date());
        sysNumber.setDate(date);
        List<SysNumber> list = this.sysNumberMapper.selectSysNumberList(sysNumber);
        Long index = new Long(1);
        //没有这个类型的编号，新增一条
        if (list.isEmpty()){
            SysNumber insertNumber = new SysNumber();
            insertNumber.setType(type);
            insertNumber.setDate(date);
            insertNumber.setIndexNo(new Long(2));
            this.sysNumberMapper.insertSysNumber(insertNumber);
        }
        //存在的话直接取，然后编号+1
        else {
            SysNumber exist = list.get(0);
            index = exist.getIndexNo();
            exist.setIndexNo(index+1);
            this.sysNumberMapper.updateSysNumber(exist);
        }

        //变三位字符
        String num = String.format("%03d", index);
        num = type + date+ num;
        return num;
    }

    @Override
    public void changeSpaPrice(Object mainInfo, Object item, String createBy, String vBillNo, String type,String vContractType) throws Exception {
        BigDecimal nPrice = BigDecimal.ZERO;
        String vSpaBrand = "";
        String supplier = "";
        String nDays = "";
        String dContract = null;
        String vType = null;
        String applyBy = null;
        BigDecimal nTotalPrice= BigDecimal.ZERO;
        BigDecimal nQty= BigDecimal.ZERO;
        String vProjectDesc =null;
        String vProjectNo = null;
        String vBuyNo = null;
        if(type.equals("BUY0003")){
            BuyPurchaseBillItem buyPurchaseBillItem = JSON.parseObject(JSON.toJSONString(item), BuyPurchaseBillItem.class);
            BuyPurchaseBill buyPurchaseBill = JSON.parseObject(JSON.toJSONString(mainInfo), BuyPurchaseBill.class);
            nPrice = buyPurchaseBillItem.getnPrice();
            vSpaBrand = buyPurchaseBillItem.getvSpaBrand();
            supplier  = buyPurchaseBillItem.getSupplier();
            nDays = buyPurchaseBillItem.getnDays();
            vBuyNo = buyPurchaseBillItem.getvBuyNo();
            vProjectNo = buyPurchaseBillItem.getvProjectNo();
            vProjectDesc = buyPurchaseBillItem.getvProjectDec();
            nPrice = buyPurchaseBillItem.getnPrice()== null ? BigDecimal.ZERO:buyPurchaseBillItem.getnPrice();
            nQty = buyPurchaseBillItem.getnQty()== null ? BigDecimal.ZERO:buyPurchaseBillItem.getnQty();
            nTotalPrice = nPrice.multiply(nQty);
            applyBy = buyPurchaseBillItem.getApplyBy();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            dContract = simpleDateFormat.format(buyPurchaseBill.getContractTime() == null?DateUtils.getNowDate():buyPurchaseBill.getContractTime());
        }else{
            BuyMaterialBillItemPO buyMaterialBillItemPO = JSON.parseObject(JSON.toJSONString(item), BuyMaterialBillItemPO.class);
            nPrice = buyMaterialBillItemPO.getnPrice();
            if (StringUtils.isEmpty(buyMaterialBillItemPO.getvSpaBrand())){
                vSpaBrand = buyMaterialBillItemPO.getvSelectBrand();
            }else{
                vSpaBrand = buyMaterialBillItemPO.getvSpaBrand();
            }
            supplier  = buyMaterialBillItemPO.getSupplier();
            nDays = buyMaterialBillItemPO.getnDays();
            vContractType = buyMaterialBillItemPO.getvKind();

        }
        //先判断备件表里有没有
        String vSpa = this.getNo("SPA");
        BuySpaMainInfoPO buySpaMainInfoPO = new BuySpaMainInfoPO();
        BeanUtils.copyBeanProp(buySpaMainInfoPO,item);
        buySpaMainInfoPO.setvSpa(vSpa);
        buySpaMainInfoPO.setiD(null);
        buySpaMainInfoPO.setvSpaBrand(vSpaBrand);
        buySpaMainInfoPO.setIsLowWarning("N");
        buySpaMainInfoPO.setIsLowQty(BigDecimal.ZERO);
        buySpaMainInfoPO.setvKind(vContractType);
        List<BuySpaMainInfoPO> spaList = this.buySpaMainInfoMapper.selectSpaInfoByConditions(buySpaMainInfoPO);
        if (spaList.size() == 0){
            this.buySpaMainInfoMapper.insertSpaMain(buySpaMainInfoPO);
        }

        //先查价格
        BuySpaPricePO buySpaPricePO = new BuySpaPricePO();
        BeanUtils.copyBeanProp(buySpaPricePO,item);
        buySpaPricePO.setvSpaBrand(vSpaBrand);
        BuySpaPricePO buySpaPriceExist = buySpaPriceMapper.selectSpaPriceByCondition(buySpaPricePO);

        //如果有旧价格，把旧价格作废
        if (buySpaPriceExist != null && buySpaPriceExist.getiD() != null && buySpaPriceExist.getiD() != 0){
            if(buySpaPriceExist.getnPrice()!=null && buySpaPriceExist.getnPrice().compareTo(nPrice) != 0){
                buySpaPriceExist.setStatus("1");
                buySpaPriceExist.setUpdateBy(createBy);
                int flag = this.buySpaPriceMapper.updateSpaPriceByID(buySpaPriceExist);
                if (flag!= 1){
                    throw new Exception("系统异常，请联系管理员");
                }
                //新增新价格
                buySpaPricePO.setStatus("0");
                buySpaPricePO.setvSpa(vSpa);
                buySpaPricePO.setCreateBy(createBy);
                buySpaPricePO.setvContractNo(vBillNo);
                buySpaPricePO.setnValidityDays(new BigDecimal(365));
                buySpaPricePO.setvKind(vContractType);
                buySpaPricePO.setSupplier(supplier);
                buySpaPricePO.setnDays(nDays);
                buySpaPricePO.setnValidityDays(new BigDecimal(365));

                buySpaPricePO.setdContract(dContract);
                buySpaPricePO.setvBuyNo(vBuyNo);
                buySpaPricePO.setvProjectNo(vProjectNo);
                buySpaPricePO.setvProjectDesc(vProjectDesc);
                buySpaPricePO.setnTotalPrice(nTotalPrice);
                buySpaPricePO.setvType(vType);
                buySpaPricePO.setApplyBy(applyBy);


                Date date = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                calendar.add(Calendar.DAY_OF_YEAR, buySpaPricePO.getnValidityDays().intValue());
                buySpaPricePO.setdValidity(calendar.getTime());
                flag = this.buySpaPriceMapper.insertSpaPrice(buySpaPricePO);
                if (flag!= 1){
                    throw new Exception("系统异常，请联系管理员");
                }
            }
        }else{
            //新增新价格
            buySpaPricePO.setStatus("0");
            buySpaPricePO.setvSpa(vSpa);
            buySpaPricePO.setCreateBy(createBy);
            buySpaPricePO.setvKind(vContractType);
            buySpaPricePO.setvContractNo(vBillNo);
            buySpaPricePO.setdContract(dContract);
            buySpaPricePO.setvBuyNo(vBuyNo);
            buySpaPricePO.setvProjectNo(vProjectNo);
            buySpaPricePO.setvProjectDesc(vProjectDesc);
            buySpaPricePO.setnTotalPrice(nTotalPrice);
            buySpaPricePO.setvType(vType);
            buySpaPricePO.setApplyBy(applyBy);
            buySpaPricePO.setnValidityDays(new BigDecimal(365));
            Date date = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_YEAR, buySpaPricePO.getnValidityDays().intValue());
            buySpaPricePO.setdValidity(calendar.getTime());
            int flag = this.buySpaPriceMapper.insertSpaPrice(buySpaPricePO);
            if (flag!= 1){
                throw new Exception("系统异常，请联系管理员");
            }
        }

        //反查明表，更新vspa
        if(type.equals("BUY0003")){
            BuyPurchaseBillItem buyPurchaseBillItem = JSON.parseObject(JSON.toJSONString(item), BuyPurchaseBillItem.class);
            List<BuyPurchaseBillItem> list = this.buyPurchaseBillItemMapper.selectBuyPurchaseBillItemList(buyPurchaseBillItem);
            if (list.size() > 0){
                buyPurchaseBillItem = list.get(0);
                buyPurchaseBillItem.setvSpa(vSpa);
                this.buyPurchaseBillItemMapper.updateBuyPurchaseBillItem(buyPurchaseBillItem);
            }
        }else{
            BuyMaterialBillItemPO buyMaterialBillItemPO = JSON.parseObject(JSON.toJSONString(item), BuyMaterialBillItemPO.class);
            List<BuyMaterialBillItemPO> list = this.buyMaterialBillItemMapper.selectMaterialBillItemCondition(buyMaterialBillItemPO);
            if (list.size() > 0){
                buyMaterialBillItemPO = list.get(0);
                buyMaterialBillItemPO.setvSpa(vSpa);
                this.buyMaterialBillItemMapper.updateMaterialBillItemByID(buyMaterialBillItemPO);
            }
        }
    }

    @Override
    public void changeInventory(Object mainInfo, List<Object> itemInfo, String vType) throws Exception {
        //新增移动单主子表，期初导入没有住业务单据
        //Object转Map
        Map map = JSONObject.parseObject(JSONObject.toJSONString(mainInfo), Map.class);
        //转主表
        InvInoutBill invInoutBill = new InvInoutBill();
        invInoutBill.setvBillNo(this.getNo(vType));
        if (vType.equals("HZOUT")){
            invInoutBill.setIotype("O");
            invInoutBill.setvType("OHZ");
        }else if(vType.equals("HZIN")){
            invInoutBill.setIotype("I");
            invInoutBill.setvType("IHZ");
        }else{
            invInoutBill.setIotype(map.get("iotype")== null?"":map.get("iotype").toString());
            invInoutBill.setvType(map.get("vType")== null?"":map.get("vType").toString());
        }
        invInoutBill.setvCorBillNo(map.get("vBillNo")== null?"":map.get("vBillNo").toString());
        String time = map.get("dExecute")== null? DateUtils.getDate() :map.get("dExecute").toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(time);
        invInoutBill.setdExecute(date);
        //新增主表
        this.invInoutBillMapper.insertInvInoutBill(invInoutBill);
        List<InvInoutBill> list = this.invInoutBillMapper.selectInvInoutBillList(invInoutBill);
        Long nMainId = list.get(0).getId();

        //转明细
        for (Object item:itemInfo
             ) {

            Map itemMap = JSONObject.parseObject(JSONObject.toJSONString(item), Map.class);
            InvInoutBillItem invInoutBillItem = new InvInoutBillItem();
            invInoutBillItem.setnMainId(nMainId);
            invInoutBillItem.setvSpa(itemMap.get("vSpa") == null?"":itemMap.get("vSpa").toString());
            invInoutBillItem.setvSpaName(itemMap.get("vSpaName").toString());
            invInoutBillItem.setvSpaModel(itemMap.get("vSpaModel").toString());
            invInoutBillItem.setvSpaBrand(itemMap.get("vSpaBrand").toString());
            invInoutBillItem.setnPrice(new BigDecimal(itemMap.get("nPrice").toString()));
            invInoutBillItem.setnQty(new BigDecimal(itemMap.get("nQty").toString()));
            invInoutBillItem.setvContractNo(map.get("vContractNo")== null?"":map.get("vContractNo").toString());
            if(vType.equals("IN")){
                invInoutBillItem.setvProjectNo(itemMap.get("vProjectNo").toString());
                invInoutBillItem.setvProjectDec(itemMap.get("vProjectDec") == null?"":itemMap.get("vProjectDec").toString());
                invInoutBillItem.setApplyBy(itemMap.get("applyBy") == null?"":itemMap.get("applyBy").toString());
            }
            else if(vType.equals("DBIN")){
                invInoutBillItem.setvProjectNo(map.get("vProjectNo").toString());
                invInoutBillItem.setvContractNo(itemMap.get("vContractNo")== null?"":itemMap.get("vContractNo").toString());
            }
            else if(vType.equals("OUT") || vType.equals("DBOUT")){
                invInoutBillItem.setvProjectNo(map.get("vProjectNo")== null?"":map.get("vProjectNo").toString());
                invInoutBillItem.setvContractNo(itemMap.get("vContractNo")== null?"":itemMap.get("vContractNo").toString());
            }
            else if(vType.equals("TK")){
                invInoutBillItem.setvProjectNo(map.get("vProjectNo").toString());
            }
            else if(vType.equals("HZOUT")){
                invInoutBillItem.setvProjectNo(null);
                invInoutBillItem.setvProjectDec(null);
                invInoutBillItem.setvBuyNo(null);
            }
            else if(vType.equals("HZIN")){
                invInoutBillItem.setvProjectDec(itemMap.get("vProjectDec") == null?null:itemMap.get("vProjectDec").toString());
                invInoutBillItem.setvProjectDec(itemMap.get("vProjectNo") == null?null:itemMap.get("vProjectNo").toString());
                invInoutBillItem.setvProjectDec(itemMap.get("vBuyNo") == null?null:itemMap.get("vBuyNo").toString());
                invInoutBillItem.setvContractNo(itemMap.get("vContractNo")== null?"":itemMap.get("vContractNo").toString());
            }
            invInoutBillItem.setvWHId(itemMap.get("vWHId").toString());
            invInoutBillItem.setvAreaId(itemMap.get("vAreaId").toString());
            invInoutBillItem.setvLocationId(itemMap.get("vLocationId").toString());
            invInoutBillItem.setvBuyNo(itemMap.get("vBuyNo") == null?null:itemMap.get("vBuyNo").toString());
            invInoutBillItem.setvOpr(this.getUsername());


            //更新库存
            //先查这个库位有没有这个库存，没有的话直接新增
            InvInventoryInfo invInventoryInfo = new InvInventoryInfo();
            invInventoryInfo.setvSpa(invInoutBillItem.getvSpa());
            invInventoryInfo.setvSpaName(invInoutBillItem.getvSpaName());
            invInventoryInfo.setvSpaModel(invInoutBillItem.getvSpaModel());
            invInventoryInfo.setvSpaBrand(invInoutBillItem.getvSpaBrand());
            invInventoryInfo.setnPrice(invInoutBillItem.getnPrice());
            invInventoryInfo.setnQty(invInoutBillItem.getnQty());
            invInventoryInfo.setvContractNo(map.get("vContractNo")== null?null:map.get("vContractNo").toString());
            if(StringUtils.isEmpty(invInventoryInfo.getvContractNo())){
                invInventoryInfo.setvContractNo(itemMap.get("vContractNo")== null?null:itemMap.get("vContractNo").toString());
            }
            invInventoryInfo.setvProjectNo(itemMap.get("vProjectNo")== null?null:itemMap.get("vProjectNo").toString());
            invInventoryInfo.setvProjectDec(itemMap.get("vProjectDec")== null?null:itemMap.get("vProjectDec").toString());
            invInventoryInfo.setvWHId(invInoutBillItem.getvWHId());
            invInventoryInfo.setvAreaId(invInoutBillItem.getvAreaId());
            invInventoryInfo.setvLocationId(invInoutBillItem.getvLocationId());
            invInventoryInfo.setvBuyNo(invInoutBillItem.getvBuyNo());
            if(vType.equals("TK")){
                invInventoryInfo.setvLotNo(itemMap.get("vLotNo")== null?null: Long.valueOf(itemMap.get("vLotNo").toString()));
            }
            if(vType.equals("HZOUT")){
                invInventoryInfo.setvProjectNo(itemMap.get("vProjectNoOld")== null?null:itemMap.get("vProjectNoOld").toString());
                invInventoryInfo.setvBuyNo(itemMap.get("vBuyNoOld")== null?null:itemMap.get("vBuyNoOld").toString());
            }
            if(vType.equals("HZIN")){
                invInventoryInfo.setvProjectNo(itemMap.get("vProjectNo")== null?null:itemMap.get("vProjectNo").toString());
                invInventoryInfo.setvBuyNo(itemMap.get("vBuyNo")== null?null:itemMap.get("vBuyNo").toString());
            }

            List<InvInventoryInfo> invInventoryInfos = new ArrayList<>();
            if (vType.equals("HZOUT")){
                invInventoryInfos = this.invInventoryInfoMapper.selectInvInventoryInfoListOrderByLotyiban(invInventoryInfo);
            }else if(vType.equals("IN")){
                invInventoryInfos = this.invInventoryInfoMapper.selectInvInventoryInfoListOrderByLotWithOutVBuyNo(invInventoryInfo);
            }else{
                invInventoryInfos = this.invInventoryInfoMapper.selectInvInventoryInfoListOrderByLot(invInventoryInfo);
            }

            /*******************************************************这一段是入库逻辑****************************/

            if(vType.equals("IN") || vType.equals("DBIN")|| vType.equals("HZIN")){
                if(invInventoryInfos.isEmpty()){
                    invInventoryInfo.setvLotNo(1L);
                    invInventoryInfo.setCreateBy(this.getUsername());
                    invInventoryInfo.setCreateTime(DateUtils.getNowDate());
                    invInoutBillItem.setvLotNo(1L);
                    invInoutBillItem.setCreateBy(this.getUsername());
                    invInoutBillItem.setCreateTime(DateUtils.getNowDate());
                    this.invInventoryInfoMapper.insertInvInventoryInfo(invInventoryInfo);
                }else{
                    //如果存在，价钱和最后一个批次价格相同的话，直接修改库存
                    InvInventoryInfo lastInvInfo = invInventoryInfos.get(invInventoryInfos.size()-1);
                    if(lastInvInfo.getnPrice().compareTo(invInoutBillItem.getnPrice())==0){
                        lastInvInfo.setnQty(invInventoryInfo.getnQty().add(invInoutBillItem.getnQty()));
                        invInventoryInfo.setUpdateBy(this.getUsername());
                        invInventoryInfo.setUpdateTime(DateUtils.getNowDate());
                        invInoutBillItem.setvLotNo(lastInvInfo.getvLotNo());
                        invInoutBillItem.setUpdateBy(this.getUsername());
                        invInoutBillItem.setUpdateTime(DateUtils.getNowDate());
                        this.invInventoryInfoMapper.updateInvInventoryInfo(lastInvInfo);
                    }
                    //如果不同的话，按下一批次新增进库存
                    else{
                        invInventoryInfo.setvLotNo(lastInvInfo.getvLotNo()+1);
                        invInventoryInfo.setCreateBy(this.getUsername());
                        invInventoryInfo.setCreateTime(DateUtils.getNowDate());
                        invInoutBillItem.setvLotNo(invInventoryInfo.getvLotNo());
                        invInoutBillItem.setCreateBy(this.getUsername());
                        invInoutBillItem.setCreateTime(DateUtils.getNowDate());
                        this.invInventoryInfoMapper.insertInvInventoryInfo(invInventoryInfo);
                    }
                }
            }
            /*******************************************************这一段是入库逻辑****************************/
            /*******************************************************这一段是出库逻辑****************************/
            else if(vType.equals("OUT") || vType.equals("DBOUT") || vType.equals("HZOUT")){
                //出库都是修改库存
                InvInventoryInfo lastInvInfo = invInventoryInfos.get(invInventoryInfos.size()-1);
                lastInvInfo.setnQty(lastInvInfo.getnQty().subtract(invInoutBillItem.getnQty()));
                invInoutBillItem.setvLotNo(lastInvInfo.getvLotNo());
                invInoutBillItem.setvContractNo(lastInvInfo.getvContractNo());
                lastInvInfo.setUpdateTime(DateUtils.getNowDate());
                lastInvInfo.setUpdateBy(this.getUsername());
                this.invInventoryInfoMapper.updateInvInventoryInfo(lastInvInfo);
            }
            /*******************************************************这一段是出库逻辑****************************/
            /*******************************************************这一段是退库逻辑****************************/
            else if(vType.equals("TK")){
                //先看这个库位有没有件
                if(invInventoryInfos.isEmpty()){
                    invInventoryInfo.setvLotNo(1L);
                    invInoutBillItem.setvLotNo(1L);
                    invInventoryInfo.setCreateBy(getUsername());
                    invInventoryInfo.setCreateTime(DateUtils.getNowDate());
                    this.invInventoryInfoMapper.insertInvInventoryInfo(invInventoryInfo);
                }else{
                    Long vLotNo = Long.valueOf(itemMap.get("vLotNo").toString());
                    List<InvInventoryInfo> filters = invInventoryInfos.stream().filter(s->s.getvLotNo() == vLotNo).collect(Collectors.toList());
                    if (filters.size() > 0){
                        filters.get(0).setnQty(filters.get(0).getnQty().add(invInoutBillItem.getnQty()));
                        this.invInventoryInfoMapper.updateInvInventoryInfo(filters.get(0));
                        invInoutBillItem.setvLotNo(vLotNo);
                    }
                }
            }
            /*******************************************************这一段是退库逻辑****************************/
            //新增移动单明细
            invInoutBillItem.setCreateBy(this.getUsername());
            invInoutBillItem.setCreateTime(DateUtils.getNowDate());
            invInoutBillItemMapper.insertInvInoutBillItem(invInoutBillItem);
        }
    }

    @Override
    public String getUsername() {
        return getLoginUser().getUsername();
    }

    @Override
    public LoginUser getLoginUser() {
        return SecurityUtils.getLoginUser();
    }

    @Override
    public void transformGeneralInventory(List<InvInventoryInfo> invInventoryInfos) {

    }
}
